package ru.dasbundos;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MultiThreadServer {

	/*
	 * Порт, на котором работает сервер
	 * */
	static final int PORT = 31007;
	
	/*
	 * Сокет для прослушки подключений.
	 * */
	static ServerSocket listenSocket;
	
	/*
	 * Количество обслуживаемых в данный момент клиентов
	 * */
	public static int mClientsConnected = 0;
	
	/*
	 * Максимальное количество обслуживаемых одновременно клиентов
	 * */
	public static final int MAX_CONNECTIONS = 20;
	
	/*
	 * Пул исполнителей
	 * */
	static ExecutorService mExecutor;

	public static void main(String[] args) {

		// создание пула потоков-исполнителей
		mExecutor = Executors.newFixedThreadPool(MAX_CONNECTIONS);
		
		try {
			listenSocket = new ServerSocket(PORT);
			System.out.println("Server started");
			while (true) {
				if (mClientsConnected >= MAX_CONNECTIONS) {
					Thread.sleep(2000);
					continue;
				}
					
				// Ожидание соединения. Блокирующий вызов.
				Socket socket = listenSocket.accept();
				
				System.out.println("Client was connected: " + socket);
				try {
					// Вызов потока обслуживания
					new ServerThread(socket);
					mClientsConnected++;
				}
				catch (IOException e) {
					// Если завершится неудачей, закрывается сокет,
					// в противном случае, поток закроет его:
					socket.close();
				}
			}
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		catch (InterruptedException e) {
			e.printStackTrace();
		}
		finally {
			try {
				listenSocket.close();
				mExecutor.shutdown();
				while (!mExecutor.isTerminated()) { }
				System.out.println("All threads in pool are finished ");
			}
			catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		// пример работы с исполнителями
		/*
		 * ExecutorService executor = Executors.newFixedThreadPool(5); for (int
		 * i = 0; i < 10; i++) { Runnable task = new
		 * ExecutableTask(String.valueOf(i)); executor.execute(task); }
		 * executor.shutdown(); while (!executor.isTerminated()) { }
		 * 
		 * System.out.println("All threads are finished ");
		 */
	}
}